from datetime import datetime
from decimal import Decimal
from typing import List, Optional

from pydantic import BaseModel, ConfigDict, EmailStr, Field, model_validator

from app.core.constants import BalanceSourceType, BoolEnum, GenderType, PointSourceType


# ============
# 基础模型
# ============

class UserBalanceRecordBase(BaseModel):
    user_id: int = Field(description="用户ID")
    amount: Decimal = Field(description="变动金额")
    before_balance: Decimal = Field(description="变动前余额")
    after_balance: Decimal = Field(description="变动后余额")
    source_type: BalanceSourceType = Field(description="来源类型")
    remark: Optional[str] = Field(description="备注")
    created_at: datetime = Field(description="创建时间")


class UserPointRecordBase(BaseModel):
    user_id: int = Field(description="用户ID")
    amount: int = Field(description="变动积分数")
    before_points: int = Field(description="变动前积分")
    after_points: int = Field(description="变动后积分")
    source_type: PointSourceType = Field(description="来源类型")
    remark: Optional[str] = Field(description="备注")
    created_at: datetime = Field(description="创建时间")


class UserBalanceRecordResponse(UserBalanceRecordBase):
    id: int = Field(description="ID")

    source_type_name: str = Field(description="来源类型名称")

    @model_validator(mode="before")
    def set_source_type_name(self, v, info):
        mapping = {
            BalanceSourceType.ADMIN: "管理员操作",
            BalanceSourceType.CONSUME: "消费",
            BalanceSourceType.REFUND: "退款",
            BalanceSourceType.RECHARGE: "充值",
            BalanceSourceType.OTHER: "其他",
        }
        self.source_type_name = mapping.get(self.source_type, "其他")
        return v


class UserPointRecordResponse(UserPointRecordBase):
    id: int = Field(description="ID")

    source_type_name: str = Field(description="来源类型名称")

    @model_validator(mode="before")
    def set_source_type_name(self, v, info):
        mapping = {
            PointSourceType.OTHER: "其他",
            PointSourceType.ADMIN: "管理员操作",
            PointSourceType.TASK: "任务",
            PointSourceType.SIGN_IN: "签到",
        }
        self.source_type_name = mapping.get(self.source_type, "其他")
        return v
